package com.xs.ahoi.hcxs.utils;

import android.graphics.*;
import android.support.v4.content.ContextCompat;
import com.xs.ahoi.hcxs.Ahoi;
import com.xs.ahoi.hcxs.R;
import com.xs.ahoi.hcxs.dao.ConfigDao;
import com.xs.ahoi.hcxs.model.vo.CharData;
import com.xs.ahoi.hcxs.model.vo.PageCharData;
import com.xs.ahoi.hcxs.service.BookFactory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * author: ahoi
 * date: 2018/7/11 12:19
 * description:
 */
public class TextSelectUtil {

    // 屏幕尺寸
    private float screenWidth, screenHeight;
    private Bitmap bitmapCurPage, bitmapNextPage;
    // 选中效果画笔
    private Paint mSelectedPaint;
    private Paint mPaint;
    // 选中文字绘制路径
    private Path mPathSelected;
    // 第一个和最后一个选中的文字
    private CharData firstChar, lastChar;
    // 本页字符集合
    private List<PageCharData> pageCharDatas;
    // 拖动滑块半径
    private float sliderRadius = Constants.SELECT_SLIDER_RADIUS;
    // 选中文字背景色   拖动滑块背景色
    private int colorPressSelect, colorPressSlider;
    // 是否触摸落在滑块区域
    private boolean isClickInFirstSlider = false, isClickInLastSlider = false;

    private ConfigDao configDao;


    // 初始化
    public TextSelectUtil(Bitmap bitmapCurPage, Bitmap bitmapNextPage, float screenWidth, float screenHeight) {
        this.bitmapNextPage = bitmapNextPage;
        this.bitmapCurPage = bitmapCurPage;
        this.screenWidth = screenWidth;
        this.screenHeight = screenHeight;

        init();
    }

    // 初始化
    private void init() {
        configDao = ConfigDao.getInstance();

        // 选中文字背景色   拖动滑块背景色
        colorPressSelect = ContextCompat.getColor(Ahoi.getInstance().getActivity(), R.color.colorPressSelect);
        colorPressSlider = ContextCompat.getColor(Ahoi.getInstance().getActivity(), R.color.colorPressSlider);

        // 初始化选中文字路径
        mPathSelected = new Path();
        // 初始化选中文字画笔
        mSelectedPaint = new Paint();
        mSelectedPaint.setAntiAlias(true);
        mSelectedPaint.setTextSize(configDao.getTextSize());
        mSelectedPaint.setColor(colorPressSelect);
        mPaint = new Paint();
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setColor(colorPressSlider);
    }

    // 绘制选中的文字
    public boolean drawStatic(Canvas canvas, float longPressX, float longPressY) {
        if (BookFactory.getInstance().isCancelPage()) {
            canvas.drawBitmap(bitmapCurPage, 0, 0, null);
        } else {
            canvas.drawBitmap(bitmapNextPage, 0, 0, null);
        }
        // 获取长按坐标附近的文字
        CharData c = CharData.getPointPress(longPressX, longPressY, pageCharDatas);
        if (c != null) {
            firstChar = CharData.getFirstByPress(pageCharDatas, c);
            lastChar = CharData.getLastByPress(pageCharDatas, c);

            // 获取首尾字符之间的文字，并绘制区域
            drawBetweenArea(canvas);

            // 测试用，绘制每个字的边框
//            for (PageCharData dd : pageCharDatas) {
//                for (CharData charData : dd.getCharData()) {
//                    canvas.drawRect(charData.getLeft(), charData.getTop(), charData.getRight(), charData.getBottom(), mPaint);
//                }
//            }

            // 绘制首尾滑块
            drawSlider(canvas);
            return true;
        }
        return false;
    }

    // 绘制拖动滑块时选中的文字
    public void drawMove(float moveX, float moveY, Canvas canvas) {
        if (BookFactory.getInstance().isCancelPage()) {
            canvas.drawBitmap(bitmapCurPage, 0, 0, null);
        } else {
            canvas.drawBitmap(bitmapNextPage, 0, 0, null);
        }

        // 获取移动坐标附近的文字
        CharData c = CharData.getPointMove(moveX, moveY, pageCharDatas);
        if (c != null) {
            // 移动尾部滑块时
            if (isClickInLastSlider) {
                // 如果移动的坐标在第一个选中文字的后面，则更新lastChar为c点
                if ((moveX >= firstChar.getRight() && moveY >= firstChar.getTop()) || (moveY >= firstChar.getBottom())) {
                    lastChar = c;
                }
                // 如果移动坐标在第一个选中文字的前面，则更新lastChar为旧的firstChar，再更新firstChar为c点
                else if ((moveX <= firstChar.getLeft() && moveY <= firstChar.getBottom()) || (moveY <= firstChar.getTop())) {
                    lastChar = firstChar;
                    firstChar = c;
                    isClickInFirstSlider = true;
                    isClickInLastSlider = false;
                }
            } else if (isClickInFirstSlider) {
                // 如果移动的坐标在最后一个选中文字的前面，则更新firstChar为c点
                if ((moveX <= lastChar.getLeft() && moveY <= lastChar.getBottom()) || (moveY <= lastChar.getTop())) {
                    firstChar = c;
                }
                // 如果移动坐标在最后一个选中文字的后面，则更新firstChar为旧的lastChar，再更新lastChar为c点
                else if ((moveX >= lastChar.getRight() && moveY >= lastChar.getTop()) || (moveY >= lastChar.getBottom())) {
                    firstChar = lastChar;
                    lastChar = c;
                    isClickInFirstSlider = false;
                    isClickInLastSlider = true;
                }
            }

            // 获取首尾字符之间的文字，并绘制区域
            drawBetweenArea(canvas);

            // 绘制首尾滑块
            drawSlider(canvas);
        }
    }

    // 获取首尾字符之间的文字，并绘制区域
    private void drawBetweenArea(Canvas canvas) {
        List<Rect> pathArea = getPathArea(pageCharDatas);
        for (Rect rect : pathArea) {
            mPathSelected.reset();
            mPathSelected.moveTo(rect.left, rect.top);
            mPathSelected.lineTo(rect.right, rect.top);
            mPathSelected.lineTo(rect.right, rect.bottom);
            mPathSelected.lineTo(rect.left, rect.bottom);
            mPathSelected.close();
            canvas.drawPath(mPathSelected, mSelectedPaint);
        }
    }

    // 绘制选中时的首尾滑块
    private void drawSlider(Canvas canvas) {
        mSelectedPaint.setColor(colorPressSlider);
        // 画右下角滑块
        mPathSelected.reset();
        mPathSelected.moveTo(lastChar.getRight(), lastChar.getBottom());
        mPathSelected.lineTo(lastChar.getRight() + sliderRadius, lastChar.getBottom());
        mPathSelected.arcTo(lastChar.getRight(), lastChar.getBottom(),
                lastChar.getRight() + sliderRadius * 2,
                lastChar.getBottom() + sliderRadius * 2,
                -90, 270, false);
        mPathSelected.close();
        canvas.drawPath(mPathSelected, mSelectedPaint);
        // 画左上角滑块
        mPathSelected.reset();
        mPathSelected.moveTo(firstChar.getLeft(), firstChar.getTop());
        mPathSelected.lineTo(firstChar.getLeft() - sliderRadius, firstChar.getTop());
        mPathSelected.arcTo(firstChar.getLeft() - sliderRadius * 2,
                firstChar.getTop() - sliderRadius * 2,
                firstChar.getLeft(),
                firstChar.getTop(),
                90, 270, false);
        mPathSelected.close();
        canvas.drawPath(mPathSelected, mSelectedPaint);

        // 还原画笔颜色为选中文字背景颜色
        mSelectedPaint.setColor(colorPressSelect);
    }

    // 绘制屏幕截图放大镜
    public void drawShortCut(Canvas canvas, Bitmap shortCut, float touchX, float touchY) {
        if (shortCut != null) {
            // 获取截图放大镜的显示位置（根据当前触摸点定位）
            float x = touchX - shortCut.getWidth() / 2;
            float y = touchY - shortCut.getHeight() * 1.5f - Constants.SHORT_CUT_MARGIN;

            // 如果上方显示不下，就显示在下方
            if (y < 0) {
                y = touchY + shortCut.getWidth() / 2 + Constants.SHORT_CUT_MARGIN;
            }
            x = x < 0 ? 0 : x;
            x = x > (screenWidth - shortCut.getWidth()) ? (screenWidth - shortCut.getWidth()) : x;
            canvas.drawBitmap(shortCut, x, y, null);
        }
    }

    // 是否点击在选中区域(分成5部分判断)
    public boolean isClickInSelectArea(float touchX, float touchY) {

        // 如果在滑块区域，直接返回true
        if (isClickInSliderArea(touchX, touchY)) {
            return true;
        }

        // 如果首尾字符在同一行，则判断是否在中间区域 或 滑块区域
        if (firstChar.getTop() == lastChar.getTop()) {
            return touchX >= firstChar.getLeft() && touchX <= lastChar.getRight() && touchY >= firstChar.getTop() && touchY <= firstChar.getBottom();
        }

        // inCenter
        return touchY >= firstChar.getBottom() && touchY <= lastChar.getTop()
                // inTop
                || touchX >= firstChar.getLeft() && touchY >= firstChar.getTop() && touchY <= firstChar.getBottom()
                // inBottom
                || touchX <= lastChar.getRight() && touchY >= lastChar.getTop() && touchY <= lastChar.getBottom();
    }

    // 是否点击在滑块区域
    private boolean isClickInSliderArea(float touchX, float touchY) {
        return isClickInFirstSlider(touchX, touchY) || isClickInLastSlider(touchX, touchY);
    }

    // 是否点击在第一个滑块区域
    public boolean isClickInFirstSlider(float touchX, float touchY) {
        return touchX >= firstChar.getLeft() - sliderRadius * 3 && touchX <= firstChar.getLeft() + sliderRadius &&
                touchY >= firstChar.getTop() - sliderRadius * 3 && touchY <= firstChar.getTop() + sliderRadius;
    }

    // 是否点击在最后一个滑块区域
    public boolean isClickInLastSlider(float touchX, float touchY) {
        return touchX >= lastChar.getRight() - sliderRadius && touchX <= lastChar.getRight() + sliderRadius * 3 &&
                touchY >= lastChar.getBottom() - sliderRadius && touchY <= lastChar.getBottom() + sliderRadius * 3;
    }

    // 获取首尾字符之间被选中的文字对应的绘制坐标
    private List<Rect> getPathArea(List<PageCharData> pageCharDatas) {
        // 获取首尾字符之间的文字
        List<CharData> betweenDatas = CharData.listBetweenFirstAndLast(firstChar, lastChar, pageCharDatas);

        // 按TopY坐标分组
        Map<Float, List<CharData>> groupByTopY = new HashMap<>();
        for (CharData data : betweenDatas) {
            List<CharData> list = groupByTopY.get(data.getTop());
            if (ObjectUtils.isNull(list)) {
                list = new ArrayList<>();
                groupByTopY.put(data.getTop(), list);
            }
            list.add(data);
        }

        // 每一个分组内按LeftX排序，并生成起止连接区域
        List<Rect> rects = new ArrayList<>();
        for (Map.Entry<Float, List<CharData>> entry : groupByTopY.entrySet()) {
            List<CharData> list = entry.getValue();
            if (ObjectUtils.isNotEmpty(list)) {
                list.sort((o1, o2) -> (int) (o1.getLeft() - o2.getLeft()));
                CharData first = list.get(0);
                CharData last = list.get(list.size() - 1);
                rects.add(new Rect((int) first.getLeft(), (int) first.getTop(), (int) last.getRight(), (int) last.getBottom()));
            }
        }
        return rects;
    }


    //**********************************************************
    //********************get set 方法**************************
    //**********************************************************

    public void setPageCharDatas(List<PageCharData> pageCharDatas) {
        this.pageCharDatas = pageCharDatas;
    }

    public void setClickInFirstSlider(boolean clickInFirstSlider) {
        isClickInFirstSlider = clickInFirstSlider;
        isClickInLastSlider = !clickInFirstSlider;
    }

    public void setClickInLastSlider(boolean clickInLastSlider) {
        isClickInLastSlider = clickInLastSlider;
        isClickInFirstSlider = !clickInLastSlider;
    }

    public CharData getFirstChar() {
        return firstChar;
    }

    public CharData getLastChar() {
        return lastChar;
    }
}
